"use strict";
// 暴露类接口
var LazyLoad = /** @class */ (function () {
    function LazyLoad(options) {
        this.options = {};
        this.root = window; // 监听的根元素
        this.defaultOptions = {
            // 默认option参数
            top: document.documentElement.clientHeight,
            left: document.documentElement.clientWidth,
            useThrottle: false,
            useDebounce: false,
            throttleTime: 200,
            debounceTime: 200,
            methods: null,
        };
        if (!isObject(options)) {
            // 判断外界参数是否是对象
            console.warn("Init warn：请检查初始化参数！");
        }
        this.options = this.setOptions(options); // 初始化option参数
        // console.log(this.options);
        this.els = this.getEls();
        this.scrollDetected(); // 为根元素绑定滚动检测事件
        this.renderImg(); // 初始化时手动触发渲染方法
    }
    // 设置options参数
    LazyLoad.prototype.setOptions = function (options) {
        var _this_1 = this;
        Object.keys(this.defaultOptions).forEach(function (key) {
            // 遍历默认options中的key值并给予设定
            _this_1.options[key] = options[key]
                ? options[key]
                : _this_1.defaultOptions[key];
        });
        return this.options;
    };
    // 获取得到懒加载图片元素
    LazyLoad.prototype.getEls = function () {
        return document.querySelectorAll("img[data-lazyload]");
    };
    // 计算触发视图条件的参数对象
    LazyLoad.prototype.calView = function () {
        var top = null;
        var left = null;
        var viewportHeight = document.documentElement.clientHeight;
        var viewportWidth = document.documentElement.clientWidth;
        if (typeof this.options.top === "number" ||
            typeof this.options.top === "string") {
            top =
                typeof this.options.top === "number"
                    ? this.options.top
                    : parseFloat(this.options.top) * viewportHeight;
        }
        if (typeof this.options.left === "number" ||
            typeof this.options.left === "string") {
            left =
                typeof this.options.left === "number"
                    ? this.options.left
                    : parseFloat(this.options.left) * viewportWidth;
        }
        return {
            viewY: top < viewportHeight ? top : viewportHeight,
            viewX: left < viewportWidth ? left : viewportWidth,
        };
    };
    // 检查元素是否隐藏
    LazyLoad.prototype.isHidden = function (elem) {
        return elem.offsetParent === null;
    };
    // 检查元素是否满足给定条件范围内
    LazyLoad.prototype.checkInView = function (elem) {
        var rect = elem.getBoundingClientRect();
        var view = this.calView();
        // console.log(rect.top);
        return rect.top < view.viewY && rect.left < view.viewX;
    };
    // 为图像元素绑定加载完成事件
    LazyLoad.prototype.onloadImg = function (elem) {
        var _this_1 = this;
        if (!this.options.methods)
            return; // 安全检测
        Object.keys(this.options.methods).forEach(function (key) {
            var bindMethod = _this_1.options.methods[key];
            elem.addEventListener("load", bindMethod);
        });
    };
    // 渲染图片并进行处理
    LazyLoad.prototype.renderImg = function () {
        var _this_1 = this;
        this.els.forEach(function (elem) {
            if (_this_1.isHidden(elem))
                return; // 检测图片的display是否生效,不生效直接返回
            if (!elem.dataset.lazyload)
                return; // 如果元素已经懒加载过了直接返回
            if (_this_1.checkInView(elem)) {
                _this_1.onloadImg(elem); // 注册加载完成事件
                elem.src = elem.dataset.lazyload;
                elem.removeAttribute("data-lazyload");
            }
        });
    };
    // 滚动事件检测
    LazyLoad.prototype.scrollDetected = function () {
        var _this = this; // 为后续绑定，防止丢失实例this
        if (this.options.useThrottle) {
            this.root.addEventListener("scroll", _throttle(this.renderImg.bind(_this), this.options.throttleTime));
        }
        else if (this.options.useDebounce) {
            this.root.addEventListener("scroll", _debounce(this.renderImg.bind(_this), this.options.debounceTime));
        }
        else {
            this.root.addEventListener("scroll", this.renderImg.bind(_this));
        }
    };
    LazyLoad.VERSION = "0.0.6";
    return LazyLoad;
}());
// 判断对象参数是否成立并提供类型推断
function isObject(target) {
    return Object.prototype.toString.call(target) === "[object Object]";
}
// 节流控制部分
function _throttle(callback, delay) {
    var canRun = true;
    var throttledFunc = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var _this = this;
        if (canRun === false) {
            return;
        }
        callback.apply(_this, args);
        canRun = false;
        setTimeout(function () {
            canRun = true;
        }, delay);
    };
    throttledFunc.cancel = function () { return (canRun = true); }; // 设置取消节流方法
    return throttledFunc;
}
// 防抖控制部分
function _debounce(callback, delay) {
    var timeId = undefined;
    var debouncedFunc = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        clearTimeout(timeId);
        var _this = this;
        timeId = setTimeout(function () {
            callback.apply(_this, args);
        }, delay);
    };
    debouncedFunc.cancel = function () { return clearTimeout(timeId); }; // 设置取消防抖方法
    return debouncedFunc;
}
